package cn.akwangl.socket;

import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.connection.channel.direct.LocalPortForwarder;
import net.schmizz.sshj.connection.channel.direct.Parameters;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;

import java.io.IOException;
import java.net.ServerSocket;

/**
 * maven 依赖:
 * <dependency>
 * <groupId>com.hierynomus</groupId>
 * <artifactId>sshj</artifactId>
 * <version>0.33.0</version>
 * </dependency>
 *
 * @author 阿坤同学
 * @date 2022/7/1 16:33
 */
public class SSHSocket {

    private static SSHClient ssh;

    /**
     * SSH 跳板机
     */
    private static String SSH_HOST = "";
    private static String SSH_USER = "";
    private static String SSH_PASSWORD = "";

    /**
     * 本地socket端口监听
     * <p>
     * 场景:
     * 服务A mysql 3306
     * <p>
     * 当你的网络与服务A不在一个网络中,那么可以使用跳板机访问.
     * 其原理就是跳板机作为代理转发你的请求与服务A的响应,底层采用的通信是socket.
     * 当你想调用更多服务时则需要监听多个{@link LocalPortForwarder}对象.
     * <p>
     * 那本地服务如何去访服务A?只需要修改连接socket地址与端口号.
     * <pre>
     *      Parameters parameters = new Parameters(LOCAL_SOCKET_HOST, LOCAL_SOCKET_PORT, REMOTE_HOST, REMOTE_PORT);
     *      ServerSocket serverSocket = new ServerSocket(3306, 200);
     * </pre>
     */
    private static String LOCAL_SOCKET_HOST = "localhost";
    private static int LOCAL_SOCKET_PORT = 3306;

    /**
     * 远程服务.
     */
    private static String REMOTE_HOST = "";
    private static int REMOTE_PORT = 3306;

    public static void init() {
        ssh = new SSHClient();
        ssh.addHostKeyVerifier(new PromiscuousVerifier());
        try {
            ssh.connect(SSH_HOST);
            ssh.authPassword(SSH_USER, SSH_PASSWORD);

            Parameters parameters = new Parameters(LOCAL_SOCKET_HOST, LOCAL_SOCKET_PORT, REMOTE_HOST, REMOTE_PORT);
            ServerSocket serverSocket = new ServerSocket(3306, 200);
            LocalPortForwarder localPortForwarder = ssh.newLocalPortForwarder(parameters, serverSocket);
            // 由于是测试代码所以就这么写了.
            new Thread(() -> {
                try {
                    localPortForwarder.listen();
                } catch (IOException e) {
                    try {
                        localPortForwarder.close();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    e.printStackTrace();
                }
            }).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
